package com.items.websocket;


import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
@ServerEndpoint(value = "/p2p")
public class P2pWebsocket {

    private final static Map<String, SessionConnect> sessionConnectMap = new HashMap<>(10);

    private final static String[] sessions = new String[10];

    @Data
    static class SessionConnect{
        Session session;
        /**
         * 发起人
         */
        String initiator;

        /**
         * 承诺人
         */
        String accepter;
    }

    /**
     *  一对一连接
     *
     * @param session   会话
     */
    @OnOpen
    public void onOpen(Session session){
        Map<String,String> map = parameter(session.getQueryString());
        String initiator = map.get("name");
        sessions[Integer.parseInt(session.getId())] = initiator;
        if (!sessionConnectMap.containsKey(initiator)){
            SessionConnect sessionConnect = new SessionConnect();
            sessionConnect.setInitiator(initiator);
            sessions[Integer.parseInt(session.getId())] = map.get("name");
            sessionConnectMap.put(initiator,sessionConnect);
        }
        sessionConnectMap.get(initiator).setSession(session);
    }

    @OnClose
    public void onClose(Session session){
        Map<String,String> map = parameter(session.getQueryString());
        String initiator = map.get("name");
        if (sessionConnectMap.containsKey(initiator)){
            sessionConnectMap.remove(initiator);
        }
        sessions[Integer.parseInt(session.getId())] = null;
    }


    private Session getAccepterSession(Session session){
        Map<String,String> map = parameter(session.getQueryString());
        String initiator = map.get("name");
        if (sessionConnectMap.containsKey(initiator)){
            return sessionConnectMap.get(sessionConnectMap.get(initiator).getAccepter()).getSession();
        }
        return null;
    }

    @OnMessage
    public void sendMessage(String message, Session session) throws IOException {
        Map<String,String> map = parameter(session.getQueryString());
        String initiator = map.get("name");
        if(sessionConnectMap.get(initiator).getAccepter().equals("all")){
            for (Session  s:session.getOpenSessions()) {
                s.getBasicRemote().sendText(message);
            }
        } else {
            Session session1 = this.getAccepterSession(session);
            assert session1 != null;
            session1.getBasicRemote().sendText(message);
        }

    }

    @OnError
    public void onError(Session session, Throwable throwable){
        log.error(session.getId());
        log.error(throwable.getLocalizedMessage());
    }

    public static List<String> getSessions(){
        return Arrays.stream(sessions).filter(Objects::nonNull).collect(Collectors.toList());
    }

    public static Map<String,String> parameter(String urlparam){
        Map<String,String> map = new HashMap<String,String>();
        String[] param =  urlparam.split("&");
        for(String keyvalue:param){
            String[] pair = keyvalue.split("=");
            if(pair.length==2){
                map.put(pair[0], pair[1]);
            }
        }
        return map;
    }

    public static void accepter(String initiator ,String accepter){
        if (sessionConnectMap.containsKey(initiator)){
            sessionConnectMap.get(initiator).setAccepter(accepter);
        }
    }
}
